package org.springblade.common.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springblade.common.utils.JdbcUtils;
import org.springblade.modules.admin.utils.MailUtil;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;

/**
 * @author Sharry
 * @since 2023/7/20
 */
@Slf4j
public class DruidFilter implements Filter {

	/**
	 * default threshold is 2000 ms
	 */
	private final static long THRESHOLD_NANO = 2100L * 1000 * 1000;

	static final String SECRET = "fOCBzdaEuNGOSa6vtosxqf";

	private final MailUtil mailUtil;

	public DruidFilter(MailUtil mailUtil) {
		this.mailUtil = mailUtil;
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		// 只有在test环境才执行
		if (!"test".equals(System.getProperty("spring.profiles.active"))) {
			filterChain.doFilter(servletRequest, servletResponse);
			return;
		}


		// Filter逻辑处理方法
		HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
		long startTime = System.nanoTime();
		filterChain.doFilter(servletRequest, servletResponse);
		long endTime = System.nanoTime();
		long executeTime = endTime - startTime;
		if (executeTime >= THRESHOLD_NANO) {
			// 获取请求路径
			String url = httpServletRequest.getRequestURI();
			// 先判断该路径是否已被记录
			if (JdbcUtils.isDuplication(url)) {
				return;
			}
//			if (JdbcUtils.isINWhiteList(url)) {
//				return;
//			}
			String tips = "详细信息请查阅Druid监控及日志";

			String webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/d99364d3-99c3-44db-853c-3ee3358ed7fe";
			// 定义 webhook 的 URL 地址
			URL targetUrl = new URL(webhook);

			// 创建一个 HTTP POST 请求
			HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection();
			connection.setRequestMethod("POST");
			connection.setDoOutput(true);

			// 设置请求头
			connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");

			// 设置请求体
			// 创建一个 JSON 对象
			HashMap<String,String> contentMap = new HashMap<>(2);
			String message = "管理端慢SQL或业务整体缓慢告警: 执行时间" + executeTime / 1000 / 1000 + " ms, 接口路径" + url + "\n" +tips;
			contentMap.put("text", message);
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("msg_type", "text");
			jsonObject.put("content",  contentMap);
			// 签名信息
			int timestamp = (int) (System.currentTimeMillis() / 1000);
			String sign = null;
			try {
				sign = GenSign(SECRET, timestamp);
			} catch (NoSuchAlgorithmException | InvalidKeyException e) {
				throw new RuntimeException(e);
			}
            jsonObject.put("timestamp", timestamp);
			jsonObject.put("sign", sign);

			// 将 JSON 对象转换为字符串
			String payload = JSON.toJSONString(jsonObject);
			connection.getOutputStream().write(payload.getBytes());

			// 获取响应状态码
			int statusCode = connection.getResponseCode();
			System.out.println("HTTP status code: " + statusCode);

			// 启用个人数据库作监听
			JdbcUtils.executeQueryAndInsert(url,executeTime / 1000 / 1000L);
		}

	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// Filter初始化方法
	}

	@Override
	public void destroy() {
		// Filter销毁方法
	}

	/**
	 * create sign message
	 * @param secret 密钥
	 * @param timestamp 时间戳
	 * @return 签名
	 * @throws NoSuchAlgorithmException 异常信息
	 * @throws InvalidKeyException 异常信息
	 */
	private static String GenSign(String secret, int timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
		//把timestamp+"\n"+密钥当做签名字符串
		String stringToSign = timestamp + "\n" + secret;
		//使用HmacSHA256算法计算签名
		Mac mac = Mac.getInstance("HmacSHA256");
		mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
		byte[] signData = mac.doFinal(new byte[]{});
		return new String(Base64.encodeBase64(signData));
	}
}

